package a_02_wizhi.M_mysql;

import java.math.BigDecimal;
import java.util.concurrent.*;

/**
 * @author FanHaibo on 2017/6/29.
 *         <p>
 *         <p>
 *         一个函数直接或间接调用自己本身,这种函数即为递归函数。 递归算法能够以一种优雅的思考方式简化问题，但由于递归通常是通过堆栈来实现的，
 *         一直背负着效率低的“臭名”。 以计算斐波那契数列为例，程序代码如下
 *         1: 尾递归
 *         2:
 */
public class RecursiveFibonacciMultiTest {

    private Integer age;

    public static void main(String[] args) throws ExecutionException, InterruptedException {

//        //2.3.6.18.108==2x3. 3x6. 6x18. 18x108.
//        BigDecimal a = new BigDecimal(2);
//        BigDecimal b = new BigDecimal(3);
//        for (int i = 0; i < 10; i++) {
////            System.out.println("a"+i+"="+a);
////            System.out.println("b"+i+"="+b);
//            BigDecimal c = b;
//            b = fx(a,b);
//            a= c;
//            System.out.println(b);
//        }
//        System.out.println(b);


        System.out.println(recursiveFib(12));

        System.out.println(recursiveFibMethodOut(12));

//        System.out.println(tailRecursiveFib(new BigDecimal(1), new BigDecimal(1), 12));
    }


    public static BigDecimal tailRecursiveFib(BigDecimal a, BigDecimal b, int n) {
        if (n < 0) return null;
        if (n == 1) return a;
        if (n == 2) return b;
        System.out.println("b" + n + ", = " + b);
        //返回值出现在函数的末尾，且没有包含其他表达式，是尾递归！
        return tailRecursiveFib(b, a.multiply(b), n - 1);

    }

    public static BigDecimal fn(int n) {
        BigDecimal f1 = new BigDecimal(2);
        BigDecimal f2 = new BigDecimal(3);

        if (n == 2) {
            return f1;
        }
        if (n == 3) {
            return f2;
        }

        BigDecimal fn = fn(n - 1).add(fn(n - 2));

        return fn;
    }

    /**
     *
     * https://baike.baidu.com/item/尾递归/554682?fr=aladdin
     *
     * 线性递归:
     * 当n = 5时
     * 对于线性递归, 他的递归过程如下:
     * Rescuvie(5)
     * {5 * Rescuvie(4)}
     * {5 * {4 * Rescuvie(3)}}
     * {5 * {4 * {3 * Rescuvie(2)}}}
     * {5 * {4 * {3 * {2 * Rescuvie(1)}}}}
     * {5 * {4 * {3 * {2 * 1}}}}
     * {5 * {4 * {3 * 2}}}
     * {5 * {4 * 6}}
     * {5 * 24}
     * 120
     *
     * 对于尾递归, 他的递归过程如下:
     * TailRescuvie(5)
     * TailRescuvie(5, 1)
     * TailRescuvie(4, 5)
     * TailRescuvie(3, 20)
     * TailRescuvie(2, 60)
     * TailRescuvie(1, 120)
     * 120
     *
     */

    //线性递归
    public static long recursiveFib(long n) {

        if (n <= 1) {
            return n;
        }

        return recursiveFib(n - 1) + recursiveFib(n - 2);
    }

    //尾递归
    public static long recursiveFibMethodIn(long n, long little, long total, long totalSize ) {

        System.out.println("第"+( totalSize - n + 1 )+"月, 共"+total+"只.");

        if (n <= 1) {
            return total;
        }else {
            return recursiveFibMethodIn(n - 1,total,(little + total),totalSize) ;
        }
    }

    //尾递归
    public static long recursiveFibMethodOut(long n) {
        if (n <= 1) {
            return n;
        }

        return recursiveFibMethodIn(n,0l,1l, n);
    }


}